package com.boatAnchorAssistant.service.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boatAnchorAssistant.pojo.entity.*;
import com.boatAnchorAssistant.pojo.enums.alarm.AlarmStatusEnum;
import com.boatAnchorAssistant.pojo.param.alarm.*;
import com.boatAnchorAssistant.pojo.vo.alarm.*;
import com.boatAnchorAssistant.pojo.dto.alarm.*;
import com.boatAnchorAssistant.pojo.vo.notice.GetNoticeVo;
import com.boatAnchorAssistant.service.config.FixedValueConfig;
import com.boatAnchorAssistant.service.repository.in.*;
import com.boatAnchorAssistant.service.service.in.AlarmService;
import nirvana.core.context.WebContext;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 【描 述】：报警列表服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 */
@Service
public class AlarmServiceImpl implements AlarmService {

    private final AlarmRepository alarmRepository;
    private final DataDictionaryRepository dataDictionaryRepository;
    private final AlarmTypeRepository alarmTypeRepository;
    private final AlarmCauseRepository alarmCauseRepository;
    private final EventGroupRepository eventGroupRepository;
    private final DeviceRepository deviceRepository;
    private final UserDataDictionaryRepository userDataDictionaryRepository;
    private final UserRepository userRepository;

    public AlarmServiceImpl(AlarmRepository alarmRepository, DataDictionaryRepository dataDictionaryRepository, AlarmTypeRepository alarmTypeRepository, AlarmCauseRepository alarmCauseRepository, EventGroupRepository eventGroupRepository, DeviceRepository deviceRepository, UserDataDictionaryRepository userDataDictionaryRepository, UserRepository userRepository) {
        this.alarmRepository = alarmRepository;
        this.dataDictionaryRepository = dataDictionaryRepository;
        this.alarmTypeRepository = alarmTypeRepository;
        this.alarmCauseRepository = alarmCauseRepository;
        this.eventGroupRepository = eventGroupRepository;
        this.deviceRepository = deviceRepository;
        this.userDataDictionaryRepository = userDataDictionaryRepository;
        this.userRepository = userRepository;
    }


    /**
     * 创建报警列表
     *
     * @param param
     */
    @Override
    public void createAlarm(CreateAlarmParam param) {
        Alarm alarm = new Alarm();
        BeanUtils.copyProperties(param, alarm);
        Long id = IdGenerator.SNOW.generate();
        alarm.setId(id);
        alarm.setStatus(AlarmStatusEnum.WAIT);
        alarmRepository.create(alarm);
    }

    /**
     * 修改报警列表
     *
     * @param param
     */
    @Override
    public void editAlarm(EditAlarmParam param) {
        Long id = param.getId();
        Alarm alarm = alarmRepository.getByIdCheck(id);
        BeanUtils.copyProperties(param, alarm);
        alarmRepository.edit(alarm);
    }

    /**
     * 移除报警列表
     *
     * @param id
     */
    @Override
    public void removeAlarm(Long id) {
        alarmRepository.removeById(id);
    }

    /**
     * 启动/禁用报警列表
     *
     * @param id
     */
    @Override
    public void enabledAlarm(Long id) {
        Alarm alarm = alarmRepository.getByIdCheck(id);
        alarm.setIsDisable(!alarm.getIsDisable());
        alarmRepository.edit(alarm);
    }

    /**
     * 更新报警状态
     * @param param
     */
    @Override
    public void updateAlarmStatus(UpdateAlarmStatusParam param) {
        Long id = param.getId();
        Alarm alarm = alarmRepository.getByIdCheck(id);
        alarm.setStatus(param.getStatus());
        alarmRepository.edit(alarm);
    }

    /**
     * 获取报警列表详情
     *
     * @param id
     * @return
     */
    @Override
    public GetAlarmVo getAlarm(Long id) {
        Alarm alarm = alarmRepository.getByIdCheck(id);
        GetAlarmVo vo = new GetAlarmVo();
        BeanUtils.copyProperties(alarm, vo);

        if (alarm.getDeviceId()!=null){
            Device device = deviceRepository.getById(alarm.getDeviceId());
            if (device!=null){
                vo.setDeviceCode(device.getCode());
            }
        }
        if (alarm.getTypeId()!=null){
            AlarmType alarmType = alarmTypeRepository.getById(alarm.getTypeId());
            if (alarmType!=null){
                vo.setTypeName(alarmType.getName());
            }
        }
        if (alarm.getEventId()!=null){
            EventGroup eventGroup = eventGroupRepository.getById(alarm.getEventId());
            if (eventGroup!=null){
                vo.setEventName(eventGroup.getName());
            }
        }
        if (alarm.getLevelId()!=null){
            DataDictionary dataDictionary = dataDictionaryRepository.getById(alarm.getLevelId());
            if (dataDictionary!=null){
                vo.setLevelName(dataDictionary.getName());
            }
        }
        if (alarm.getAreaId()!=null){
            DataDictionary dataDictionary = dataDictionaryRepository.getById(alarm.getAreaId());
            if (dataDictionary!=null){
                vo.setAreaName(dataDictionary.getName());
            }
        }
        return vo;
    }

    /**
     * 获取最近的一条报警
     * @return
     */
    @Override
    public GetAlarmVo selectOneAlarm() {
        GetAlarmVo vo = new GetAlarmVo();
        List<Alarm> notices = alarmRepository.getBaseMapper()
                .selectList(new LambdaQueryWrapper<Alarm>()
                        .eq(Alarm::getIsDisable, false)
                        .orderByDesc(Alarm::getCreateTime)
                        .last("limit 1"));
        if (notices.size() > 0) {
            Alarm alarm = notices.get(0);
            vo=getAlarm(alarm.getId());
        }
        return vo;
    }

    /**
     * 获取报警列表 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetAlarmListVo> getAlarmList(GetAlarmListParam param) {

        SelectAlarmDto dto = new SelectAlarmDto();
        BeanUtils.copyProperties(param, dto);
        //如果需要数据隔离的话，需要在这里设置dto的查询条件
        if (param.getIsDataSegregation()!=null && param.getIsDataSegregation()){
            Long userId= WebContext.getCurrentUserId();
            User user = userRepository.getByIdCheck(userId);
            if (!user.getIsSystem()){
                if (user.getAuthorizedType()!=null && user.getAuthorizedType()!=2){
                    List<Long> ids = userDataDictionaryRepository.selectByUserIdAndTypeId(FixedValueConfig.AREA_ID, userId);
                    if (CollectionUtil.isEmpty(ids)){
                        return new PageResult<>(new ArrayList<>(),new Page<>());
                    }
                    dto.setDataSegregationIds(ids);
                }
            }
        }

        Page<Alarm> page = alarmRepository.selectAlarm(dto);
        List<Alarm> alarmList = page.getRecords();
        List<GetAlarmListVo> list = new ArrayList<>();

        if (CollectionUtil.isNotEmpty(alarmList)){
            List<Long> systemIds = new ArrayList<>();
            List<Long> typeIds=new ArrayList<>();
            List<Long> eventIds=new ArrayList<>();
            List<Long> deviceIds=new ArrayList<>();

            alarmList.stream().forEach(alarm -> {
                systemIds.add(alarm.getLevelId());
                systemIds.add(alarm.getAreaId());
                typeIds.add(alarm.getTypeId());
                eventIds.add(alarm.getEventId());
                deviceIds.add(alarm.getDeviceId());
            });

            Map<Long, DataDictionary> dictionaryMap = dataDictionaryRepository.getMap(systemIds);
            Map<Long, AlarmType> alarmTypeMap = alarmTypeRepository.getMap(typeIds);
            Map<Long, EventGroup> eventGroupMap = eventGroupRepository.getMap(eventIds);
            Map<Long, Device> deviceMap = deviceRepository.getMap(deviceIds);

            for (Alarm alarm : alarmList) {
                GetAlarmListVo vo = new GetAlarmListVo();
                BeanUtils.copyProperties(alarm, vo);

                if (CollectionUtil.isNotEmpty(dictionaryMap)) {
                    DataDictionary dataDictionary = dictionaryMap.get(alarm.getLevelId());
                    if (dataDictionary != null) {
                        vo.setLevelName(dataDictionary.getName());
                    }
                    dataDictionary = dictionaryMap.get(alarm.getAreaId());
                    if (dataDictionary != null) {
                        vo.setAreaName(dataDictionary.getName());
                    }
                }
                if (CollectionUtil.isNotEmpty(deviceMap)) {
                    Device device = deviceMap.get(alarm.getDeviceId());
                    if (device != null) {
                        vo.setDeviceCode(device.getCode());
                    }
                }
                if (CollectionUtil.isNotEmpty(alarmTypeMap)) {
                    AlarmType type = alarmTypeMap.get(alarm.getTypeId());
                    if (type != null) {
                        vo.setTypeName(type.getName());
                    }
                }
                if (CollectionUtil.isNotEmpty(eventGroupMap)) {
                    EventGroup eventGroup = eventGroupMap.get(alarm.getEventId());
                    if (eventGroup != null) {
                        vo.setEventName(eventGroup.getName());
                    }
                }
                list.add(vo);
            }
        }


        return new PageResult<>(list, page);

    }

    /**
     * 获取报警列表下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetAlarmDownListVo> getAlarmDownList(GetAlarmDownListParam param) {
        List<GetAlarmDownListVo> list = new ArrayList<>();
        LambdaQueryWrapper<Alarm> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Alarm::getIsDisable, false);

        //数据隔离
        if (param.getIsDataSegregation()!=null && param.getIsDataSegregation()){
            Long userId= WebContext.getCurrentUserId();
            User user = userRepository.getByIdCheck(userId);
            if (!user.getIsSystem()){
                if (user.getAuthorizedType()!=null && user.getAuthorizedType()!=2){
                    List<Long> ids = userDataDictionaryRepository.selectByUserIdAndTypeId(FixedValueConfig.AREA_ID, userId);
                    if (CollectionUtil.isNotEmpty(ids)){
                        wrapper.in(Alarm::getAreaId,ids);
                    }else{
                        return list;
                    }
                }
            }
        }

        List<Alarm> alarmList = alarmRepository.getBaseMapper().selectList(wrapper);
        for (Alarm alarm : alarmList) {
            GetAlarmDownListVo vo = new GetAlarmDownListVo();
            BeanUtils.copyProperties(alarm, vo);
            list.add(vo);
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cleanAlarmLevel() {
        //计算报警时间是15天之前的
        LocalDateTime alarmTime = LocalDateTime.now().minusDays(15);

        List<Alarm> alarms = alarmRepository.getBaseMapper().selectList(
                new LambdaQueryWrapper<Alarm>()
                        .notIn(Alarm::getPushLevelCode, "3")
                        .lt(Alarm::getAlarmTime, alarmTime)
                        .eq(Alarm::getIsDelete, false)
        );

        if (CollectionUtil.isNotEmpty(alarms)){
            //批量删除
            List<Long> ids = alarms.stream().map(Alarm::getId).collect(Collectors.toList());
            alarmRepository.removeBatchByIds(ids);
        }
    }

    /**
     * 事件报警查询
     * @param param
     * @return
     */
    @Override
    public List<GetAlarmChartListVo> getAlarmChartList(GetAlarmChartListParam param) {
        GetAlarmChartListDto dto = new GetAlarmChartListDto();
        BeanUtils.copyProperties(param, dto);
        List<GetAlarmChartListVo> list = alarmRepository.getAlarmChartList(dto);
        return list;
    }


}



